跳到主要内容

高级排序算法 桶排序

桶排序的介绍

桶排序(Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶里。每个桶再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序),最后依次把各个桶中的记录列出来记得到有序序列。

桶排序基本思想

1、将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后从最低位开始,依次进行一次排序。这样从最低位排序一直 到最高位排序完成以后,数列就变成一个有序序列。

2、这样说明,比较难理解,下面我们看一个图文解释,理解基数排序的步骤

什么时候最快:当输入的数据可以均匀的分配到每一个桶中。

什么时候最慢:当输入的数据被分配到了同一个桶中。

动图演示

桶排序适用数据范围

桶排序可用于最大最小值相差较大的数据情况,比如 [9012,19702,39867,68957,83556,102456]

但桶排序要求数据的分布必须均匀,否则可能导致数据都集中到一个桶中。比如 [104,150,123,132,20000],这种数据会导致前 4 个数都集中到同一个桶中。导致桶排序失效

代码实现

public class BucketSort implements IArraySort {

private static final InsertSort insertSort = new InsertSort();

@Override
public int[] sort(int[] sourceArray) throws Exception {
// 对 arr 进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);

return bucketSort(arr, 5);
}

private int[] bucketSort(int[] arr, int bucketSize) throws Exception {
if (arr.length == 0) {
return arr;
}

int minValue = arr[0];
int maxValue = arr[0];

// 先选出最大值和最小值
for (int value : arr) {
if (value < minValue) {
minValue = value;
} else if (value > maxValue) {
maxValue = value;
}
}

//桶数(因为下面也是用过这个映射函数来分配位置的,所以这里直接使用一样的映射函数)
// floor 函数用于向下取整
int bucketCount = (int) Math.floor((maxValue - minValue) / bucketSize) + 1;
// 使用二维数组,其实也可以使用下面 ArrayList,它会自动扩容
// ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
int[][] buckets = new int[bucketCount][0];

// 利用映射函数将数据分配到各个桶中(其实有点像 HashMap 的工作原理,不过它是避免冲突,而这里无需避免)
for (int i = 0; i < arr.length; i++) {
int index = (int) Math.floor((arr[i] - minValue) / bucketSize);
buckets[index] = arrAppend(buckets[index], arr[i]);
}

int arrIndex = 0;
for (int[] bucket : buckets) {
if (bucket.length <= 0) {
continue;
}

// 对每个桶进行排序,这里使用了插入排序
bucket = insertSort.sort(bucket);
for (int value : bucket) {
arr[arrIndex++] = value;
}
}

return arr;
}

/**
* 自动扩容,并保存数据
*
* @param arr
* @param value
*/
private int[] arrAppend(int[] arr, int value) {
// 对 arr 进行拷贝,不改变参数内容,这里是扩容一位
arr = Arrays.copyOf(arr, arr.length + 1);
arr[arr.length - 1] = value;
return arr;
}

}